local modeNormal = 0
local modeRedwood = 1
local mode = 0
local plantSaplings = true
local farmWidth = 8
local farmDepth = 8
local maxHeight = 12
local useFarmOffset = false
local farmOffsetWidth = -21
local farmOffsetDepth = 3
local farmOffsetHeight = 3
local redwoodTreeSpacing = 10
local normalTreeSpacing = 6
local numberOfTrees = 0
local numberOfSaplings = 0
local currentTree = 0
local removeObstacles = false
local fuelSlot = 1
local endOfTrees = "Reached end of trees, moving to start"
local treeFound = "Tree detected, commencing harvesting"
local noTreeFound = "No tree detected at current location"
local treeHarvested = "Tree harvesting completed"
local saplingHarvested = "Sapling harvested"
local next = "Proceeding to next tree"
local previous = "Returning to previous tree"
local refuelingTurtle = "Low fuel detected, refueling"
local outOfFuel = "Turtle out of fuel, waiting for refuel"
local outOfSaplings = "Turtle out of saplings, add more"
local plantingSapling = "Planting sapling"
local plantingRedwoodSaplings = "Planting redwood samplings"
local treeError = "Error harvesting current tree"
local obstacleEncountered = "Obstacle encountered, waiting"
local author = "Kevin Scroggins"
local nickname = "nitro glycerine"
local email = "nitro404@gmail.com
local website = "http://www.nitro404.com"

function checkFuel()
  if turtle.getItemCount(fuelSlot) == 0 then
    print(outOfFuel)
    
    while turtle.getItemCount(fuelSlot) == 0 do
      os.sleep(1)
    end
  end
  
  if turtle.getFuelLevel() < 15 then
    print(refuelingTurtle)
    turtle.select(fuelSlot)
    if turtle.refuel(1) ~= true then
      print(outOfFuel)
      
      while turtle.refuel(1) ~= true do
        os.sleep(1)
      end
    end
    
    checkFuel()
  end
end

function forward(d)
  if d == nil then
    d = 1
  elseif d < 1 then
    return
  end
  
  for i = 0, d - 1, 1 do
    checkFuel()
    
    if turtle.forward() ~= true then
      print(obstacleEncountered)
      
      while turtle.forward() ~= true do
        checkFuel()
        
        if removeObstacles == true then
          turtle.dig()
        end
        
        os.sleep(0.5)
      end
    end
  end
  
  checkFuel()
end

function back(d)
  if d == nil then
    d = 1
  elseif d < 1 then
    return
  end
  
  for i = 0, d - 1, 1 do
    checkFuel()
    
    if turtle.back() ~= true then
      print(obstacleEncountered)
      
      while turtle.back() ~= true do
        checkFuel()
        
        os.sleep(0.5)
      end
    end
  end
  
  checkFuel()
end

function up(d)
  if d == nil then
    d = 1
  elseif d < 1 then
    return
  end
  
  for i = 0, d - 1, 1 do
    checkFuel()
    
    if turtle.up() ~= true then
      print(obstacleEncountered)
      
      while turtle.up() ~= true do
        checkFuel()
        
        if removeObstacles == true then
          turtle.digUp()
        end
        
        os.sleep(0.5)
      end
    end
  end
  
  checkFuel()
end

function down(d)
  if d == nil then
    d = 1
  elseif d < 1 then
    return
  end
  
  for i = 0, d - 1, 1 do
    checkFuel()
    
    if turtle.down() ~= true then
      print(obstacleEncountered)
      
      while turtle.down() ~= true do
        checkFuel()
        
        if removeObstacles == true then
          turtle.digDown()
        end
        os.sleep(0.5)
      end
    end
  end
  
  checkFuel()
end

function left(n)
  if n == nil then
    n = 1
  elseif n < 1 then
    return
  end
  
  for i = 0, n - 1, 1 do
    turtle.turnLeft()
  end
end

function right(n)
  if n == nil then
    n = 1
  elseif n < 1 then
    return
  end
  
  for i = 0, n - 1, 1 do
    turtle.turnRight()
  end
end

function previousTree()
  checkFuel()
  
  print(previous)
  
  turtle.turnLeft()
  
  for j = 0, redwoodTreeSpacing - 1, 1 do
    checkFuel()
    
    turtle.forward()
  end
  
  turtle.turnRight()
  
  return true
end

function nextTree()
  local distance = 0
  
  checkFuel()
  
  print(next)
  
  turtle.turnRight()
  
  for i = 0, redwoodTreeSpacing - 1, 1 do
    checkFuel()
    
    if turtle.forward() then
      distance = distance + 1
    else
      print(endOfTrees)
      
      turtle.turnLeft()
      turtle.turnLeft()
      for j = 0, distance - 1, 1 do
        forward()
      end
      turtle.turnRight()
      
      return false
    end
  end
  
  turtle.turnLeft()
  
  if turtle.detect() ~= true then
    print(endOfTrees)
    
    return false
  end
  
  return true
end

function harvestUp()
  checkFuel()
  
  turtle.dig()
  if turtle.digUp() ~= true then
    return false
  end
  up()
  
  return true
end

function harvestDown()
  turtle.digDown()
  down()
  turtle.dig()
  
  return true
end

function checkSaplings()
  while turtle.getItemCount(2) == 0 do
    print(outOfSaplings)
    
    while turtle.getItemCount(2) == 0 do
      os.sleep(1)
    end
  end
end

function plantSapling()
  checkFuel()
  
  turtle.turnLeft()
  turtle.turnLeft()
  
  checkSaplings()
  turtle.select(2)
  turtle.place()
  
  turtle.turnLeft()
  turtle.turnLeft()
  
  return true
end

function checkRedwoodSaplings()
  while turtle.getItemCount(2) < 4 do
    print(outOfSaplings)
    
    while turtle.getItemCount(2) < 4 do
      os.sleep(1)
    end
  end
end

function plantRedwoodSaplings()
  forward()
  up()
  checkRedwoodSaplings()
  turtle.select(2)
  turtle.placeDown()
  forward()
  turtle.placeDown()
  turtle.turnRight()
  turtle.forward()
  turtle.turnRight()
  turtle.placeDown()
  forward()
  turtle.placeDown()
  turtle.dig()
  forward()
  down()
  turtle.turnRight()
  forward()
  turtle.turnRight()
  
  return true
end

function harvestTree()
  local height = 0
  
  checkFuel()
  
  if turtle.detect() == true then
    write("Harvesting tree #")
    write(currentTree + 1)
    write("\n")
    
    turtle.dig()
    forward()
    
    while turtle.detectUp() == true do
      if maxHeight > 0 and height == maxHeight - 1 then
        break
      end
      
      turtle.digUp()
      up()
      
      height = height + 1
    end
  
    for i = height - 1, 0, -1 do
      down()
    end
    
    if height == 0 then
      numberOfSaplings = numberOfSaplings + 1
      
      print(saplingHarvested)
    else
      numberOfTrees = numberOfTrees + 1
      
      print(treeHarvested)
    end
	
	currentTree = currentTree + 1
    
    forward()
  else
    print(noTreeFound)
    
    forward()
    forward()
  end
  
  if plantSaplings == true then
    print(plantingSapling)
  
    plantSapling()
  end
end

function harvestRedwoodTree()
  local height = 0
  
  if turtle.detect() == true then
    print(treeFound)
    write("Harvesting tree #")
    write(numberOfTrees + 1)
    write("\n")
  else
    print(noTreeFound)
    return false
  end
  
  turtle.dig()
  forward()
  
  while harvestUp() do
    height = height + 1
  end
  
  turtle.turnRight()
  up()
  forward()
  turtle.turnLeft()
  
  for i = height, 0, -1 do
    harvestDown()
  end
  
  back()
  turtle.turnLeft()
  forward()
  turtle.turnRight()
  
  numberOfTrees = numberOfTrees + 1
  
  print(treeHarvested)
  
  if plantSaplings == true then
    print(plantingRedwoodSaplings)
    
    plantRedwoodSaplings()
  end
  
  return true
end

function goToFarm()
  local w = 0
  local d = 0
  local h = 0
  
  while d ~= farmOffsetDepth do
    if farmOffsetDepth > 0 then
      forward()
      d = d + 1
    elseif farmOffsetDepth < 0 then
      back()
      d = d - 1
    end
  end
  
  while h ~= farmOffsetHeight do
    if farmOffsetHeight > 0 then
      up()
      h = h + 1
    elseif farmOffsetHeight < 0 then
      down()
      h = h - 1
    end
  end
  
  if farmOffsetWidth > 0 then
    turtle.turnRight()
  elseif farmOffsetWidth < 0 then
    turtle.turnLeft()
  end
  
  while w ~= farmOffsetWidth do
    forward()
    if farmOffsetWidth > 0 then
      w = w + 1
    elseif farmOffsetWidth < 0 then
      w = w - 1
    end
  end
  
  if farmOffsetWidth > 0 then
    turtle.turnLeft()
  elseif farmOffsetWidth < 0 then
    turtle.turnRight()
  end
end

function returnFromFarm()
  local w = farmOffsetWidth
  local d = farmOffsetDepth
  local h = farmOffsetHeight
  
  if farmOffsetWidth > 0 then
    turtle.turnLeft()
  elseif farmOffsetWidth < 0 then
    turtle.turnRight()
  end
  
  while w ~= 0 do
    forward()
    if farmOffsetWidth > 0 then
      w = w - 1
    elseif farmOffsetWidth < 0 then
      w = w + 1
    end
  end
  
  if farmOffsetWidth > 0 then
    turtle.turnLeft()
  elseif farmOffsetWidth < 0 then
    turtle.turnRight()
  end
  
  while h ~= 0 do
    if farmOffsetHeight > 0 then
      down()
      h = h - 1
    elseif farmOffsetHeight < 0 then
      up()
      h = h + 1
    end
  end
  
  while d ~= 0 do
    if farmOffsetDepth > 0 then
      forward()
      d = d - 1
    elseif farmOffsetDepth < 0 then
      back()
      d = d + 1
    end
  end
  
  turtle.turnRight()
  turtle.turnRight()
end

function harvestTrees()
  local direction = 0
  
  if useFarmOffset == true then
    print("Going to tree farm")
    goToFarm()
  end
  
  if mode == modeRedwood then
    while harvestRedwoodTree() do
      if nextTree() ~= true then
        break
      end
    end
    
    for i = 0, numberOfTrees - 2, 1 do
      previousTree()
    end
  elseif mode == modeNormal then
    for i = 0, farmWidth - 1, 1 do
      for j = 0, farmDepth - 1, 1 do
        harvestTree()
        
        if j < farmDepth - 1 then
          for k = 0, normalTreeSpacing - 3, 1 do
            forward()
          end
        end
      end
      
      if i < farmWidth - 1 then
        if direction == 0 then
          turtle.turnRight()
        else
          turtle.turnLeft()
        end
        
        for k = 0, normalTreeSpacing - 1, 1 do
          forward()
        end
        
        if direction == 0 then
          turtle.turnRight()
          direction = 1
        else
          turtle.turnLeft()
          direction = 0
        end
      end
    end
    
    if direction == 0 then
      turtle.turnRight()
      forward()
      turtle.turnRight()
      for i = 0, farmDepth - 2 do
        for j = 0, normalTreeSpacing - 1 do
          forward()
        end
      end
      forward()
      forward()
      turtle.turnRight()
      forward()
    else
      turtle.turnRight()
    end
    
    for i = 0, farmWidth - 2 do
      for j = 0, normalTreeSpacing - 1 do
        forward()
      end
    end
    turtle.turnRight()
  end
  
  write("Harvested ")
  write(numberOfTrees)
  if numberOfTrees == 1 then
    write(" tree and ")
  else
    write(" trees and ")
  end
  write(numberOfSaplings)
  if numberOfSaplings == 1 then
    write(" sapling\n")
  else
    write(" saplings\n")
  end
  
  if useFarmOffset == true then
    print("Returning to original position")
    returnFromFarm()
    print("Done!")
  end
  
  return true
end

harvestTrees()
